/*******************************************************************************
 * Copyright (c) 2011-11-10 @author <a href="mailto:iffiff1@hotmail.com">Tyler Chen</a>.
 * All rights reserved.
 *
 * Contributors:
 *     <a href="mailto:iffiff1@hotmail.com">Tyler Chen</a> - initial API and implementation
 ******************************************************************************/
package com.redhat.auth.ejb.impl;

import java.util.ArrayList;
import java.util.List;

import javax.ejb.Remote;
import javax.ejb.Stateless;

import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import com.dayatang.domain.InstanceFactory;
import com.dayatang.querychannel.service.QueryChannelService;
import com.dayatang.querychannel.support.Page;
import com.redhat.auth.domain.FunctionEntity;
import com.redhat.auth.domain.FunctionEntityType;
import com.redhat.auth.domain.FunctionEntity.Status;
import com.redhat.auth.ejb.FunctionEntityApplication;
import com.redhat.auth.ejb.vo.FunctionEntityVO;

/**
 * @author <a href="mailto:iffiff1@hotmail.com">Tyler Chen</a> 
 * @since 2011-11-10
 */
@Service("ramsFunctionEntityApplication")
@Stateless(name = "FunctionEntityApplicationBean")
@Remote(FunctionEntityApplication.class)
@javax.interceptor.Interceptors(SpringEJBIntercepter.class)
public class FunctionEntityApplicationImpl implements FunctionEntityApplication {

	protected static QueryChannelService queryChannel;

	protected static QueryChannelService getQueryChannel() {
		if (queryChannel == null) {
			queryChannel = InstanceFactory
					.getInstance(QueryChannelService.class);
		}
		return queryChannel;
	}

	public List<FunctionEntityVO> queryChildNode(Long id, int currentPage,
			int pageSize) {
		FunctionEntity entity = new FunctionEntity();
		entity.setId(id);

		List<FunctionEntityVO> list = new ArrayList<FunctionEntityVO>();
		List<FunctionEntity> query = entity.getChild();
		if (query == null) {
			return list;
		}
		for (FunctionEntity fe : query) {
			list.add(toFunctionEntityVO(fe));
		}
		return list;
	}

	public FunctionEntityVO createFunctionEntity(FunctionEntityVO vo) {
		FunctionEntity entity = toFunctionEntity(vo);
		// 如果未指定父实体则设置默认父实体为root节点ID
		if (entity.getFunctionEntityType() == null
				|| entity.getFunctionEntityType().getId() == null) {
			FunctionEntityType type = getDefaultFunctionEntityType_();
			entity.setFunctionEntityType(type);
		} else {
			entity.setFunctionEntityType(FunctionEntityType.get(vo
					.getFunctionEntityType().getId()));
		}
		if (entity.getParent() != null) {
			entity.setParent(FunctionEntity.get(entity.getParent().getId()));
		}
		return toFunctionEntityVO(entity.create());
	}

	public void deleteFunctionEntityById(Long id) {
		//查找关联子实体
		FunctionEntity entity = FunctionEntity.get(id);
		if (entity != null) {
			entity.delete();
		}
	}

	public Long getCount(FunctionEntityVO vo) {
		StringBuffer hql = new StringBuffer();
		Object[] obj = createQueryParams(vo, hql);
		return getQueryChannel().queryResultSize(hql.toString(), obj);
	}

	public FunctionEntityVO getFunctionEntityById(Long id) {
		FunctionEntity entity = FunctionEntity.get(id);
		return toFunctionEntityVO(entity);
	}

	public List<FunctionEntityVO> queryAllByPage(FunctionEntityVO vo,
			int currentPage, int pageSize) {
		StringBuffer hql = new StringBuffer();
		Object[] obj = createQueryParams(vo == null ? null : vo, hql);
		Page<FunctionEntity> page = getQueryChannel().queryPagedResult(
				hql.toString(), obj, currentPage, pageSize);
		List<FunctionEntityVO> list = new ArrayList<FunctionEntityVO>();
		List<FunctionEntity> query = page.getResult();
		if (query == null) {
			return list;
		}
		for (FunctionEntity fe : query) {
			list.add(toFunctionEntityVO(fe));
		}
		return list;
	}

	public FunctionEntityVO updateFunctionEntity(FunctionEntityVO vo) {
		FunctionEntity entity = FunctionEntity.get(vo.getId());
		if (entity == null) {
			return null;
		}
		{
			if (vo.getAlias() != null) {
				entity.setAlias(vo.getAlias());
			}
			if (vo.getDescription() != null) {
				entity.setDescription(vo.getDescription());
			}
			if (vo.getName() != null) {
				entity.setName(vo.getName());
			}
			if (vo.getStatus() == FunctionEntity.Status.ENABLED.ordinal()) {
				entity.setStatus(FunctionEntity.Status.ENABLED);
			} else if (vo.getStatus() == FunctionEntity.Status.DISABLED
					.ordinal()) {
				entity.setStatus(FunctionEntity.Status.DISABLED);
			}
			if (vo.getFunctionEntityType() != null
					&& vo.getFunctionEntityType().getId() != null) {
				FunctionEntityType type = FunctionEntityType.get(vo
						.getFunctionEntityType().getId());
				if (type != null) {
					entity.setFunctionEntityType(type);
				}
			}
		}
		return toFunctionEntityVO(entity.update());
	}

	public void setRelevance(long rscId, long destId) {

	}

	public void changStatus(Long id, int functionEntityStatus) {
		FunctionEntity funEntity = FunctionEntity.get(id);
		if (Status.ENABLED.ordinal() == functionEntityStatus) {
			funEntity.enable();
		} else if (Status.DISABLED.ordinal() == functionEntityStatus) {
			funEntity.disable();
		}
	}

	public List<FunctionEntityVO> queryFunctionEntity(FunctionEntityVO vo) {
		List<Object> params = new ArrayList<Object>();
		String hql = "from FunctionEntity e where 1=1 ";
		String name = vo != null ? vo.getName() : null;
		String alias = vo != null ? vo.getAlias() : null;
		name = (name == null || (name = name.trim()).length() < 1) ? alias
				: name;
		alias = (alias == null || (alias = alias.trim()).length() < 1) ? name
				: alias;
		if (name != null && (name = name.trim()).length() > 0) {
			hql += " and e.name like ?";
			params.add("%" + name + "%");
		}
		if (alias != null && (alias = alias.trim()).length() > 0) {
			hql += " and e.alias like ?";
			params.add("%" + alias + "%");
		}
		{
			hql += " order by e.name ";
		}
		List<FunctionEntity> list = getQueryChannel().queryResult(hql,
				params.toArray());
		List<FunctionEntityVO> result = new ArrayList<FunctionEntityVO>();
		for (FunctionEntity fe : list) {
			result.add(toFunctionEntityVO(fe));
		}
		return result;
	}

	public Page<FunctionEntityVO> pageQueryFunctionEntity(FunctionEntityVO vo,
			int currentPage, int pageSize) {
		List<Object> params = new ArrayList<Object>();
		String hql = "from FunctionEntity e where 1=1 ";
		String name = vo != null ? vo.getName() : null;
		String alias = vo != null ? vo.getAlias() : null;
		name = (name == null || (name = name.trim()).length() < 1) ? alias
				: name;
		alias = (alias == null || (alias = alias.trim()).length() < 1) ? name
				: alias;
		if (name != null && (name = name.trim()).length() > 0) {
			hql += " and e.name like ?";
			params.add("%" + name + "%");
		}
		if (alias != null && (alias = alias.trim()).length() > 0) {
			hql += " and e.alias like ?";
			params.add("%" + alias + "%");
		}
		{
			hql += " order by e.name ";
		}
		Page<FunctionEntity> page = getQueryChannel().queryPagedResultByPageNo(
				hql, params.toArray(), currentPage, pageSize);
		List<FunctionEntityVO> result = new ArrayList<FunctionEntityVO>();
		List<FunctionEntity> list = page.getResult();
		for (FunctionEntity fe : list) {
			result.add(toFunctionEntityVO(fe));
		}
		return PageUtil.toPage(page, result);
	}

	public FunctionEntityVO getDefaultRootFunctionEntity() {
		return toFunctionEntityVO(getDefaultRootFunctionEntity_());
	}

	private FunctionEntityType getDefaultFunctionEntityType_() {
		FunctionEntityType dafaultNode = null;
		List<FunctionEntityType> rootNodes = getQueryChannel().queryResult(
				"from FunctionEntityType t where t.name=?",
				new Object[] { "ROOT" });
		if (rootNodes == null || rootNodes.isEmpty()) {
			dafaultNode = new FunctionEntityType(null, "ROOT", null);
			dafaultNode.save();
		} else {
			dafaultNode = rootNodes.get(0);
		}
		return dafaultNode;
	}

	private FunctionEntity getDefaultRootFunctionEntity_() {
		FunctionEntity dafaultNode = null;
		List<FunctionEntity> rootNodes = getQueryChannel().queryResult(
				"from FunctionEntity f where f.parent is NULL", new Object[0]);

		if (rootNodes == null || rootNodes.isEmpty()) {
			dafaultNode = new FunctionEntity();
			dafaultNode.setParent(null);
			dafaultNode.setAlias(" ");
			dafaultNode.setName("root");
			dafaultNode.create();
		} else {
			dafaultNode = rootNodes.get(0);
		}
		return dafaultNode;
	}

	/**
	 * 构造查询条件
	 * @param vo
	 * @param hql
	 * @return
	 */
	private Object[] createQueryParams(FunctionEntityVO vo, StringBuffer hql) {
		hql.append("select f from FunctionEntity f");
		List<Object> params = new ArrayList<Object>();
		if (vo != null) {
			if (vo.getFunctionEntityType() != null) {
				hql.append(" join f.functionEntityType type where type.id=?");
				params.add(vo.getFunctionEntityType().getId());
			} else {
				hql.append(" where 1=1");
			}

			if (StringUtils.isNotBlank(vo.getName())) {
				hql.append(" and f.name like ?");
				params.add("%" + vo.getName() + "%");
			}

			if (StringUtils.isNotBlank(vo.getAlias())) {
				hql.append(" and f.name like ?");
				params.add("%" + vo.getAlias() + "%");
			}

			if (vo.getStatus() == FunctionEntity.Status.ENABLED.ordinal()) {
				hql.append(" and f.status=?");
				params.add(FunctionEntity.Status.ENABLED);
			} else if (vo.getStatus() == FunctionEntity.Status.DISABLED
					.ordinal()) {
				hql.append(" and f.status=?");
				params.add(FunctionEntity.Status.DISABLED);
			}
		}
		Object[] obj = params.isEmpty() ? new Object[] {} : params.toArray();
		return obj;
	}

	private FunctionEntity toFunctionEntity(FunctionEntityVO vo) {
		return Convertor.vo2po(vo, new FunctionEntity());
	}

	private FunctionEntityVO toFunctionEntityVO(FunctionEntity entity) {
		return Convertor.po2vo(entity, null);
	}
}
